package com.huilian.iotbox.admin.wap.aopLog;

import com.huilian.iotbox.admin.wap.service.*;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.enums.LogManipulateTypeEnum;
import com.huilian.iotbox.data.enums.OperationLogEnum;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.service.LogManipulateService;
import com.huilian.iotbox.data.utils.Util;
import com.huilian.iotbox.data.vo.DeviceVo;
import com.huilian.iotbox.data.vo.OrderVo;
import com.huilian.iotbox.data.vo.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author: loong
 * @create: 2023-04-24 09:45
 **/
@Aspect
@Slf4j
@Component
public class LogAspect {
    @Resource
    private UserService userService;
    @Resource
    private OrderService orderService;
    @Resource
    private DeviceService deviceService;
    @Resource
    private MemberService memberService;
    @Resource
    private ErrorLogCommonService errorLogCommonService;
    @Resource
    private MerchantStoreService merchantStoreService;
    @Resource
    private LogManipulateService logManipulateService;
    @Resource
    private CommodityService commodityService;

    @Around("@annotation(operateLog)")
    public Object aroundLog(ProceedingJoinPoint point, OperateLog operateLog) {

        StopWatch started = new StopWatch();
        LogManipulate logManipulate = new LogManipulate();
        ServerResponse proceed = null;
        try {
            //记录进来接口时间
            logManipulate.setRequestDateTime(new Date());
            //计时开始
            started.start();
            //获取返回参数
            proceed = (ServerResponse) point.proceed();

            return proceed;
        } catch (RuntimeException e) {
            e.printStackTrace();
            errorLogCommonService.writerInfoException("切面捕抓到异常_1", "proceed", e);
            logManipulate.setErrorMsg(e.getMessage());
            proceed = ServerResponse.createByErrorMessage(e.getMessage());
            throw e;
        } catch (Throwable throwable) {
            errorLogCommonService.writerInfoException("切面捕抓到异常_2", "proceed", null);
            throwable.printStackTrace();
            logManipulate.setErrorMsg(throwable.getMessage());
            proceed = ServerResponse.createByErrorMessage(throwable.getMessage());
            throw new RuntimeException(throwable.getMessage());
        } finally {
            started.stop();

            //获取用户信息
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
            UserInfo userInfo = userService.getLoginUserInfo(request);

            logManipulate.setUserId(userInfo.getId());
            logManipulate.setIp(Util.getIpAddress(request));
            logManipulate.setPlace(null);
            Map<String, String> map = Util.getDevice(request.getHeader("User-Agent"));
            logManipulate.setBrowser(map.get("browser"));
            logManipulate.setSystem(map.get("system"));

            //整个接口访问时间
            logManipulate.setResponseDateTime(started.getTime());

            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
//            //获取方法名
            String methodName = method.getName();
            String className = method.getDeclaringClass().getName();

            logManipulate.setMethodName(className + "." + methodName);

            Object[] objects = point.getArgs();

            String remark = null;
            String param = null;
            String r1;
            String r2;
            String r3;
            String r4;

            if (className.contains("DeviceController")) {
                DeviceVo deviceVo;
                DeviceDto deviceDto = (DeviceDto) objects[0];
                param = deviceDto.toString();

                switch (methodName) {
                    case "updateDeviceRemarkNameById":
                        r1 = StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = StringUtils.isEmpty(deviceDto.getDeviceNo()) ? "" : "(" + deviceDto.getDeviceNo() + ")";
                        remark = r1 + r2 + "修改设备备注名称为：" + deviceDto.getRemarkName() + ",设备" + r3;

                        logManipulate.setType(LogManipulateTypeEnum.DEVICE_BIND.getCode());
                        logManipulate.setDeviceNo(deviceDto.getDeviceNo());
                        break;
                    case "getSynchronizationStock":
                        r1 = StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        remark = r1 + r2 + "给设备(" + deviceDto.getDeviceNo() + ")同步并全部补满库存";

                        logManipulate.setType(LogManipulateTypeEnum.GIFT_BIND.getCode());
                        logManipulate.setDeviceNo(deviceDto.getDeviceNo());
                        break;
                    case "updateDeviceById":
                        r1 = StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = StringUtils.isEmpty(deviceDto.getDeviceNo()) ? "" : "(" + deviceDto.getDeviceNo() + ")";
                        remark = r1 + r2 + "修改投币数为" + deviceDto.getRateEach() + ",设备" + r3;

                        logManipulate.setType(LogManipulateTypeEnum.DEVICE_BIND.getCode());
                        logManipulate.setDeviceNo(deviceDto.getDeviceNo());
                        break;
                    case "updateUnbindDevice":
                        r1 = StringUtils.isEmpty(deviceDto.getUsername()) ? "" : deviceDto.getUsername();
                        r2 = StringUtils.isEmpty(deviceDto.getName()) ? "" : "(" + deviceDto.getName() + ")";
                        r3 = StringUtils.isEmpty(r1 + r2) ? "" : "的";
                        r4 = StringUtils.isEmpty(deviceDto.getDeviceNo()) ? "" : "(" + deviceDto.getDeviceNo() + ")";
                        remark = "解绑" + r1 + r2 + r3 + "设备" + r4;

                        logManipulate.setType(LogManipulateTypeEnum.DEVICE_UNBIND.getCode());
                        logManipulate.setDeviceNo(deviceDto.getDeviceNo());
                        break;
                }
            } else if (className.contains("RemoteStartController")) {
                ConsumeRecordDto consumeRecordDto = (ConsumeRecordDto) objects[0];
                param = consumeRecordDto.toString();

                switch (methodName) {
                    case "upCoin":
                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        remark = r1 + r2 + "给设备(" + consumeRecordDto.getDeviceNo() + ")远程上分" + consumeRecordDto.getConsume() + "个币";


                        logManipulate.setType(LogManipulateTypeEnum.REMOTE_START.getCode());
                        logManipulate.setDeviceNo(consumeRecordDto.getDeviceNo());
                        break;
                }
            } else if (className.contains("BlackListController")) {
                BlackListDto blackListDto = (BlackListDto) objects[0];
                param = blackListDto.toString();
                logManipulate.setDeviceNo(null);
                MemberDto memberDto;

                switch (methodName) {
                    case "insert":
                        memberDto = memberService.queryById(blackListDto.getMemberId());
                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        remark = r1 + r2 + "把会员" + memberDto.getNickName() + "添加到黑名单";

                        logManipulate.setType(LogManipulateTypeEnum.BLACK_LIST_OPERATE.getCode());
                        break;
                    case "delete":
                        memberDto = memberService.queryById(blackListDto.getMemberId());
                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        remark = r1 + r2 + "把会员" + memberDto.getNickName() + "移出黑名单";

                        logManipulate.setType(LogManipulateTypeEnum.BLACK_LIST_OPERATE.getCode());
                        break;
                }
            } else if (className.contains("UserController")) {
                logManipulate.setDeviceNo(null);

                switch (methodName) {
                    case "subAccountRegister":
                        UserStoreDto userStoreDto = (UserStoreDto) objects[0];
                        param = userStoreDto.toString();

                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = com.alibaba.druid.util.StringUtils.isEmpty(userStoreDto.getUser().getMobile()) ? "" : userStoreDto.getUser().getMobile();
                        r4 = com.alibaba.druid.util.StringUtils.isEmpty(userStoreDto.getUser().getName()) ? "" : "(" + userStoreDto.getUser().getName() + ")";
                        remark = r1 + r2 + "添加子账号" + r3 + r4;

                        logManipulate.setType(LogManipulateTypeEnum.SUB_ACCOUNT_OPERATE.getCode());
                        break;
                    case "deleteSubAccountByUserId":
                        UserDto userDto = (UserDto) objects[0];
                        param = userDto.toString();

                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = com.alibaba.druid.util.StringUtils.isEmpty(userDto.getUsername()) ? "" : userDto.getUsername();
                        r4 = com.alibaba.druid.util.StringUtils.isEmpty(userDto.getName()) ? "" : "(" + userDto.getName() + ")";
                        remark = r1 + r2 + "删除子账号" + r3 + r4;

                        logManipulate.setType(LogManipulateTypeEnum.SUB_ACCOUNT_OPERATE.getCode());
                        break;

                }
            } else if (className.contains("UserAllocationModuleController")) {
                UserAllocationModuleDto userAllocationModuleDto = (UserAllocationModuleDto) objects[0];
                userAllocationModuleDto.setAllocationModuleList(null);
                param = userAllocationModuleDto.toString();
                logManipulate.setDeviceNo(null);

                switch (methodName) {
                    case "editAllocationModule":
                        UserDto userDto = new UserDto();
                        userDto.setUserInfo(userInfo);
                        userDto.setUserId(userAllocationModuleDto.getUserId());
                        User subUser = userService.findSubUserId(userDto);

                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = com.alibaba.druid.util.StringUtils.isEmpty(subUser.getUsername()) ? "" : subUser.getUsername();
                        r4 = com.alibaba.druid.util.StringUtils.isEmpty(subUser.getName()) ? "" : "(" + subUser.getName() + ")";
                        remark = r1 + r2 + "修改子账号" + r3 + r4;

                        logManipulate.setType(LogManipulateTypeEnum.SUB_ACCOUNT_OPERATE.getCode());
                        break;
                }
            } else if (className.contains("FeedbackController")) {
                FeedbackDto feedbackDto = (FeedbackDto) objects[0];
                param = feedbackDto.toString();
                logManipulate.setDeviceNo(null);

                switch (methodName) {
                    case "editAllocationModule":
                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        MemberDto memberDto = memberService.queryById(feedbackDto.getMemberId());
                        String nickName = StringUtils.isEmpty(memberDto.getNickName()) ? "" : memberDto.getNickName();
                        remark = r1 + r2 + "给" + nickName + "派发福利" + feedbackDto.getSendCoin() + "个币";

                        logManipulate.setType(LogManipulateTypeEnum.SEND_WELFARE.getCode());
                        break;
                }
            } else if (className.contains("DiscountPackageController")) {
                DiscountPackageDto discountPackageDto = (DiscountPackageDto) objects[0];
                param = discountPackageDto.toString();
                logManipulate.setDeviceNo(null);

                MerchantStoreDto merchantStoreDto;
                MerchantStore merchantStore;
                switch (methodName) {
                    case "editPackage":
                        merchantStoreDto = new MerchantStoreDto();
                        merchantStoreDto.setId(discountPackageDto.getMerchantStoreId());
                        merchantStoreDto.setUserInfo(userInfo);
                        merchantStore = merchantStoreService.findOneMerchantStoreByIdAndPermission(merchantStoreDto);

                        r1 = StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = !ObjectUtils.isEmpty(discountPackageDto.getId()) ? "修改" : "添加";
                        remark = r1 + r2 + "为场地(" + merchantStore.getStoreName() + ")" + r3 + "套餐";

                        logManipulate.setType(LogManipulateTypeEnum.PACKAGE_OPERATE.getCode());
                        break;
                    case "deletePackage":
                        merchantStoreDto = new MerchantStoreDto();
                        merchantStoreDto.setId(discountPackageDto.getMerchantStoreId());
                        merchantStoreDto.setUserInfo(userInfo);
                        merchantStore = merchantStoreService.findOneMerchantStoreByIdAndPermission(merchantStoreDto);

                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        remark = r1 + r2 + "为场地(" + merchantStore.getStoreName() + ")删除套餐";

                        logManipulate.setType(LogManipulateTypeEnum.PACKAGE_OPERATE.getCode());
                        break;
                }
            }  else if (className.contains("OrderRefundController")) {
                OrderRefundDto orderRefundDto = (OrderRefundDto) objects[0];
                param = orderRefundDto.toString();

                switch (methodName) {
                    case "refund":
                        OrderVo orderVo = orderService.findOneOrderByOutTradeNo(orderRefundDto.getOutTradeNo(), userInfo);

                        r1 = StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        remark = r1 + r2 + "给" + orderVo.getStoreName() + "的" + orderVo.getNickName() + "申请退款";

                        logManipulate.setDeviceNo(orderVo.getDeviceNo());
                        logManipulate.setType(LogManipulateTypeEnum.REFUND_OPERATE.getCode());
                        break;
                }
            } else if (className.contains("MerchantStoreController")) {
                MerchantStoreDto merchantStoreDto = (MerchantStoreDto) objects[0];
                param = merchantStoreDto.toString();
                logManipulate.setDeviceNo(null);
                switch (methodName) {
                    case "save":
                        r1 = StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = merchantStoreDto.getId() > 0 ? "修改" : "添加";
                        remark = r1 + r2 + r3 + "场地";

                        logManipulate.setType(LogManipulateTypeEnum.SITE_OPERATE.getCode());
                        break;
                    case "saveByApplet":
                        r1 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getUsername()) ? "" : userInfo.getUsername();
                        r2 = com.alibaba.druid.util.StringUtils.isEmpty(userInfo.getName()) ? "" : "(" + userInfo.getName() + ")";
                        r3 = merchantStoreDto.getId() > 0 ? "修改" : "添加";
                        remark = r1 + r2 + r3 + "场地";

                        logManipulate.setType(LogManipulateTypeEnum.SITE_OPERATE.getCode());
                        break;
                }
            }

            if (!StringUtils.isEmpty(param) && param.length() > 5000) {
                param = param.substring(0, 5000);
            }
            logManipulate.setParam(param);

            if (OperationLogEnum.STATUS_SUCC.getCode().equals(Util.stringConvert(proceed.getStatus()))) {
                logManipulate.setStatus(OperationLogEnum.STATUS_SUCC.getCode());
                remark = remark + "成功";
            } else {
                logManipulate.setStatus(OperationLogEnum.STATUS_FAIL.getCode());
                remark = remark + "失败";
            }
            logManipulate.setRemark(remark);
            logManipulateService.add(logManipulate);
        }
    }
}
